package com.soo.hoo.admin.config;

import cn.dev33.satoken.context.SaHolder;
import cn.dev33.satoken.exception.NotLoginException;
import cn.dev33.satoken.filter.SaServletFilter;
import cn.dev33.satoken.router.SaRouter;
import cn.dev33.satoken.stp.StpUtil;
import com.alibaba.fastjson2.JSON;
import com.soo.hoo.core.exception.GlobalException;
import com.soo.hoo.core.model.Result;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
 * <p>
 * saToken认证配置
 * </p>
 *
 * @author 杨燚
 * @see <a href="https://sa-token.dev33.cn/doc/index.html#/up/global-filter">saToken全局过滤器</a>
 * @since 2022-05-18
 */
@Configuration
public class SaTokenAuthConfig {


    @Bean
    public SaServletFilter getSaServletFilter() {
        // 1、swagger相关路由放行
        // 2、单点登录相关请求放行
        return new SaServletFilter()
                .addInclude(
                        "/**"
                ).addExclude(
                        "/favicon.ico", "/swagger-ui/**", "/swagger-resources/**", "/v3/api-docs/**",
                        "/webjars/**","/doc.html","/ws/**","/image/**", "/user/login","/app/wxLogin"
                ).setAuth(
                        auth -> SaRouter.match("/**", () -> {
                            try {
                                StpUtil.checkLogin();
                                StpUtil.updateLastActiveToNow();
                            } catch (NotLoginException e) {
                                String type = e.getType();
                                String message;
                                if (NotLoginException.NOT_TOKEN.equals(type)) {
                                    message = "尚未登录，请先登录";
                                } else if (NotLoginException.INVALID_TOKEN.equals(type)) {
                                    message = "登录失效，请重新登录";
                                } else if (NotLoginException.TOKEN_TIMEOUT.equals(type)
                                        || NotLoginException.BE_REPLACED.equals(type)
                                        || NotLoginException.KICK_OUT.equals(type)) {
                                    message = "登录已过期，请重新登录";
                                } else {
                                    message = "尚未登录，请先登录";
                                }
                                throw new GlobalException(401, message);
                            }
                        })
                ).setError(
                        err -> {
                            // 由于过滤器中抛出的异常不进入全局异常处理，所以你必须提供[异常处理函数]来处理[认证函数]里抛出的异常。
                            // 在[异常处理函数]里的返回值，将作为字符串输出到前端，如果需要定制化返回数据，请注意其中的格式转换。
                            // 设置响应头
                            SaHolder.getResponse().setHeader("Content-Type", "application/json;charset=UTF-8");
                            return JSON.toJSONString(Result.failure(401, err.getMessage()));
                        }
                ).setBeforeAuth(r -> SaHolder.getResponse()
                        .setServer("api-server")
                        .setHeader("X-Frame-Options", "SAMEORIGIN")
                        .setHeader("X-XSS-Protection", "1; mode=block")
                        .setHeader("X-Content-Type-Options", "nosniff"));
    }

}
